package com.wxmit.framework.quartz.utils;

import com.wxmit.framework.quartz.exception.TaskException;
import com.wxmit.framework.quartz.jobdetail.QuartzDisallowConcurrentExecution;
import com.wxmit.framework.quartz.constants.SchedulerConstants;
import com.wxmit.framework.quartz.domain.SysJob;
import com.wxmit.framework.quartz.jobdetail.QuartzJobExecution;
import org.quartz.*;

/**
 * 定时任务工具类
 *
 * @author ruoyi
 *
 */
public class SchedulerUtils {

    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException {
        Class<? extends Job> jobClass = getQuartzJobClass(job);
        //构建job信息
        Long jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();

        // cron表达式构建
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);

        // 根据cron表达式，新增一个触发器
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
                .withSchedule(cronScheduleBuilder).build();

        // 放入参数，运行时的方法可以获取
        jobDetail.getJobDataMap().put(SchedulerConstants.TASK_PROPERTIES, job);
        //判断调度器中是否存在
        if(scheduler.checkExists(getJobKey(jobId,jobGroup))){
            //先移除，再重新创建
            scheduler.deleteJob(getJobKey(jobId,jobGroup));
        }
        //调度器装填 任务+触发器
        scheduler.scheduleJob(jobDetail,trigger);

        // 暂停任务
        if (job.getStatus().equals(SchedulerConstants.Status.PAUSE.getValue()))
        {
            scheduler.pauseJob(SchedulerUtils.getJobKey(jobId, jobGroup));
        }
    }



    private static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cronScheduleBuilder) throws TaskException {
        switch (job.getMisfirePolicy())
        {
            case SchedulerConstants.MISFIRE_DEFAULT:
                return cronScheduleBuilder;
            case SchedulerConstants.MISFIRE_IGNORE_MISFIRES:
                return cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
            case SchedulerConstants.MISFIRE_FIRE_AND_PROCEED:
                return cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
            case SchedulerConstants.MISFIRE_DO_NOTHING:
                return cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
            default:
                throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
                        + "' cannot be used in cron schedule tasks", TaskException.Code.CONFIG_ERROR);
        }
    }

    /**
     * 生成任务key
     */
    public static JobKey getJobKey(Long jobId, String jobGroup) {
        return JobKey.jobKey(SchedulerConstants.TASK_PROPERTIES+jobId,jobGroup);
    }

    /**
     * 生成触发器key
     */
    private static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
        return TriggerKey.triggerKey(SchedulerConstants.TASK_CLASS_NAME+jobId,jobGroup);
    }

    /**
     * 获取任务的具体执行类 可并发/不可并发
     */
    private static Class<? extends Job> getQuartzJobClass(SysJob job) {
        return SchedulerConstants.IS_CONCURRENT.equals(job.getConcurrent()) ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
    }

}
